﻿using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace APP.OpenCV
{
    public static class OpenCVExtensions
    {
        public static Tuple<byte, byte, byte> Vec3bConvertToTupple(this Vec3b vec)
        {
            return new Tuple<byte, byte, byte>(vec.Item0, vec.Item1, vec.Item2);
        }
        public static Vec3b TuppleConvertToVec3b(this Tuple<byte, byte, byte> vec)
        {
            return new Vec3b(vec.Item1, vec.Item2, vec.Item3);
        }

        public static Scalar GetMean(this Mat srcbit)
        {
            Mat img_hsv = new Mat();
            Cv2.CvtColor(srcbit, img_hsv, ColorConversionCodes.BGR2HSV);
            Cv2.MeanStdDev(img_hsv, out Scalar mean, out Scalar stddev);
            return mean;
        }


        public static Vec3b GetHSV(this Mat srcbit, System.Drawing.Point point, out Vec3b hsv, out System.Drawing.Color color)
        {
            hsv = new Vec3b();
            color = Color.Empty;
            try
            {
                Mat img_hsv = new Mat();
                Mat img_rgb = new Mat();
                Cv2.CvtColor(srcbit, img_hsv, ColorConversionCodes.BGR2HSV);
                Cv2.CvtColor(srcbit, img_rgb, ColorConversionCodes.BGR2RGB);
                var vec3b_hsv = img_hsv.At<Vec3b>(point.Y, point.X);
                var vec3b_rgb = img_rgb.At<Vec3b>(point.Y, point.X);

                hsv = vec3b_hsv;
                color = OpenCVHelper.HsvColor(vec3b_hsv);


                return vec3b_hsv;
            }
            catch (Exception ex)
            {

            }

            return hsv;
        }

        public static void GetHSVFromArea(this Mat srcbit, System.Drawing.Point startPoint, System.Drawing.Point endPoint, out Vec3b minHSV, out Vec3b maxHSV)
        {

            int x_srtart = Math.Min(startPoint.X, endPoint.X);
            int x_end = Math.Max(startPoint.X, endPoint.X);

            int y_srtart = Math.Min(startPoint.Y, endPoint.Y);
            int y_end = Math.Max(startPoint.Y, endPoint.Y);

            List<Vec3b> allColors = new List<Vec3b>();
            Mat img_hsv = new Mat();
            Cv2.CvtColor(srcbit, img_hsv, ColorConversionCodes.BGR2HSV);
            for (int x = x_srtart; x <= x_end; x++)
            {
                for (int y = y_srtart; y <= y_end; y++)
                {
                    try
                    {
                        var vec3b = img_hsv.At<Vec3b>(y, x);
                        allColors.Add(vec3b);
                    }
                    catch (Exception ex)
                    {

                    }
                }
            }
            var H_Max = allColors.Max(x => x.Item0);
            var S_Max = allColors.Max(x => x.Item1);
            var V_Max = allColors.Max(x => x.Item2);

            var H_Min = allColors.Min(x => x.Item0);
            var S_Min = allColors.Min(x => x.Item1);
            var V_Min = allColors.Min(x => x.Item2);

            minHSV = new Vec3b(H_Min, S_Min, V_Min);
            maxHSV = new Vec3b(H_Max, S_Max, V_Max);
        }

        public static void GetHSVFromArea(this Mat srcbit, out Vec3b minHSV, out Vec3b maxHSV, out Scalar mean)
        {

            int x_srtart = 0;
            int x_end = srcbit.Cols;

            int y_srtart = 0;
            int y_end = srcbit.Rows;

            List<Vec3b> allColors = new List<Vec3b>();
            Mat img_hsv = new Mat();
            Cv2.CvtColor(srcbit, img_hsv, ColorConversionCodes.BGR2HSV);
            for (int x = x_srtart; x <= x_end; x++)
            {
                for (int y = y_srtart; y <= y_end; y++)
                {
                    try
                    {
                        var vec3b = img_hsv.At<Vec3b>(y, x);
                        allColors.Add(vec3b);
                    }
                    catch (Exception ex)
                    {

                    }
                }
            }
            var H_Max = allColors.Max(x => x.Item0);
            var S_Max = allColors.Max(x => x.Item1);
            var V_Max = allColors.Max(x => x.Item2);

            var H_Min = allColors.Min(x => x.Item0);
            var S_Min = allColors.Min(x => x.Item1);
            var V_Min = allColors.Min(x => x.Item2);

            minHSV = new Vec3b(H_Min, S_Min, V_Min);
            maxHSV = new Vec3b(H_Max, S_Max, V_Max);

            Cv2.MeanStdDev(img_hsv, out mean, out Scalar stddev);

        }

        public static void GetRGBFromArea(this Mat srcbit, out Vec3b minHSV, out Vec3b maxHSV)
        {
            int x_srtart = 0;
            int x_end = srcbit.Cols;

            int y_srtart = 0;
            int y_end = srcbit.Rows;

            List<Vec3b> allColors = new List<Vec3b>();
            //Mat img_hsv = new Mat();
            //BGR2
            //Cv2.CvtColor(srcbit, img_hsv, ColorConversionCodes.BGR2HSV);
            for (int x = x_srtart; x <= x_end; x++)
            {
                for (int y = y_srtart; y <= y_end; y++)
                {
                    try
                    {
                        var vec3b = srcbit.At<Vec3b>(y, x);
                        allColors.Add(vec3b);
                    }
                    catch (Exception ex)
                    {

                    }
                }
            }
            var B_Max = allColors.Max(x => x.Item0);
            var G_Max = allColors.Max(x => x.Item1);
            var R_Max = allColors.Max(x => x.Item2);

            var B_Min = allColors.Min(x => x.Item0);
            var G_Min = allColors.Min(x => x.Item1);
            var R_Min = allColors.Min(x => x.Item2);

            minHSV = new Vec3b(R_Min, G_Min, B_Min);
            maxHSV = new Vec3b(R_Max, G_Max, B_Max);
        }
    }

}
